#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import cgi
import os
import random

import gdata.service
import gdata.urlfetch
# Configure gdata python client to use app engine URL Fetch
gdata.service.http_request_handler = gdata.urlfetch

from gdata.spreadsheet.service import SpreadsheetsService

from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app


class CardflasherClient(SpreadsheetsService):
  """Handle communication with the spreadsheet gdata service"""

  def  __init__(self):
    SpreadsheetsService.__init__(self)
    self.source = "markstahl-cardflasher-0.9"
    # Default config: use Client Login, talk to a hardwired spreadsheet
    self.email = 'markstahl.api@gmail.com'
    self.password = 'testtest'
    self.ProgrammaticLogin()
    self.spreadsheet_key = 'pFTNU5W-U0barlRKCdCAaKg'
    self.worksheet_key = 'od6'

  def getAllEntries(self):
    """ Get all cards in the card stack"""
    feed = self.GetListFeed(self.spreadsheet_key, self.worksheet_key)
    return feed.entry

  def getEntry(self, url):
    """Get one card in the card stack"""
    return self.Get(url, converter=gdata.spreadsheet.SpreadsheetsListFromString)

  def updateEntry(self, url, entry):
    return self.Put(entry, url, converter=gdata.spreadsheet.SpreadsheetsListFromString)

  def insertEntry(self, key_dict):
    return self.InsertRow(key_dict, self.spreadsheet_key, self.worksheet_key)

  def deleteEntry(self, edit_url):
    return self.Delete(edit_url)


class Card:
  """The data from one flashcard"""

  def initFromEntry(self, entry, client):
    """Initialize card from gdata entry"""
    self.front = entry.custom["front"].text
    self.back = entry.custom["back"].text
    score = entry.custom["score"].text
    if score == None:
      self.score = 0
    else:
      self.score = int(score)
    self.edit_url = ""
    for link in entry.link:
      if link.rel == 'edit':
        self.edit_url = link.href
        break
    self.client = client
    return self

  def initFromEditUrl(self, edit_url, client):
    """Initialize card from the gdata edit url"""
    entry = client.getEntry(edit_url)
    return self.initFromEntry(entry, client)

  def Create(self, front, back, client):
    """insert a new row into the spreadsheet"""
    key_dict = {}
    key_dict["front"] = str(front)
    key_dict["back"] = str(back)
    key_dict["score"] = str(0)
    entry = client.insertEntry(key_dict)
    self.initFromEntry(entry, client)
    return self

  def Delete(self):
    self.client.deleteEntry(self.edit_url)

  def UpdateScore(self, new_score):
    """Modify the score of a card"""
    entry = self.client.getEntry(self.edit_url)
    entry.custom["score"].text = str(new_score)
    self.client.updateEntry(self.edit_url, entry)


class RootHandler(webapp.RequestHandler):
  def get(self):
    self.redirect('/question')


class ShowQuestion(webapp.RequestHandler):
  def get(self):
    # Get a client that talks to the configured spreadsheet
    client = CardflasherClient()
    # Build the stack of cards from Spreadsheet data
    entries = client.getAllEntries()
    # Convert entries to card stack
    cards = []
    for entry in entries:
      cards.append(Card().initFromEntry(entry, client))
    # Choose card at random
    index = random.randint(0, len(cards)-1)
    card = cards[index]
    # show the question page
    template_dict = {
      'card'           : card,
    }
    path = os.path.join(os.path.dirname(__file__), 'templates/question.html');
    self.response.out.write(template.render(path, template_dict))


class ShowAnswer(webapp.RequestHandler):
  def post(self):
    # get the card data from the spreadsheet using gdata
    client = CardflasherClient()
    card = Card().initFromEditUrl(self.request.get('edit_url'), client)
    # show the answer page
    template_dict = {
      'card'           : card,
    }
    path = os.path.join(os.path.dirname(__file__), 'templates/answer.html');
    self.response.out.write(template.render(path, template_dict))


class UpdateCard(webapp.RequestHandler):
  def post(self):
    # get the card data from the spreadsheet using gdata
    client = CardflasherClient()
    card = Card().initFromEditUrl(self.request.get('edit_url'), client)
    # increment the score on this card
    if self.request.get('correct') == 'yes':
      card.score = card.score+1
      card.UpdateScore(card.score)
      
    # show result, so we can see it's been updated
    template_dict = {
      'card'           : card,
    }
    path = os.path.join(os.path.dirname(__file__), 'templates/updated.html');
    self.response.out.write(template.render(path, template_dict))


class ListCards(webapp.RequestHandler):
  def get(self):
    client = CardflasherClient()
    entries = client.getAllEntries()
    cards = []
    for entry in entries:
      cards.append(Card().initFromEntry(entry, client))
    # show the list page
    template_dict = {
      'cards'          : cards,
      'spreadsheet_url': "http://spreadsheets.google.com/ccc?key=pFTNU5W-U0barlRKCdCAaKg"
     }
    path = os.path.join(os.path.dirname(__file__), 'templates/list.html');
    self.response.out.write(template.render(path, template_dict))


class InsertCard(webapp.RequestHandler):
  def post(self):
    # add card to spreadsheet
    client = CardflasherClient()
    card = Card().Create(self.request.get('front'), self.request.get('back'), client)
    self.redirect('/list')


class DeleteCard(webapp.RequestHandler):
  def post(self):
    # get the card data from the spreadsheet using gdata
    client = CardflasherClient()
    card = Card().initFromEditUrl(self.request.get('edit_url'), client)
    card.Delete()
    self.redirect('/list')

class UnknownUrl(webapp.RequestHandler):
  def get(self):
    self.redirect('/')


def main():
  application = webapp.WSGIApplication(
    [
      ('/', RootHandler),
      ('/question', ShowQuestion),
      ('/answer', ShowAnswer),
      ('/update', UpdateCard),
      ('/list', ListCards),
      ('/insert', InsertCard),
      ('/delete', DeleteCard),
      (r'/.*', UnknownUrl),
    ],
    debug=True)
  run_wsgi_app(application)


if __name__ == '__main__':
  main()
